package com.sy.cloud.guess.controller;

import com.alibaba.fastjson.JSONObject;
import com.gok.pay.wx.*;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.sy.cloud.guess.model.PayOrder;
import com.sy.cloud.guess.model.WxConfig;
import com.sy.cloud.guess.service.IWxConfigService;
import com.sy.cloud.wechat.ConstantsPlaceholder;
import com.sy.cloud.wechat.WeChatConfig;
import com.sy.cloud.wechat.service.AuthorizeService;
import com.sy.cloud.wechat.utils.HttpUtils;
import com.sy.common.persistence.BaseService;
import com.sy.common.service.IBaseService;
import com.sy.common.service.ITestService;
import com.sy.common.util.Funutil;
import com.sy.shiro.UsernameToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.converters.DoubleConverter;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/**
 * Created by mac on 2017/12/27.
 */
@Controller
@Slf4j
@RequestMapping("/wxpay")
public class PayController {
    @Resource
    private IWxConfigService wxConfigService;

    @Resource
    private AuthorizeService authorizeService;

    @Resource
    private ITestService testService;

    @Resource
    private IBaseService baseService;


    public WXPay getWxPay() throws Exception {
        WXPayConfig wxPayConfig = wxConfigService.getWxPayConfig();
        return new WXPay(wxPayConfig,false,false);
    }
    /**
     * 千禧公众号支付
     * @return
     */
    @RequestMapping(value = "/wechatpublicpay", method = RequestMethod.GET)
    public String qxindex(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String type = request.getParameter("type");// 是充值金币还是vip充值  值是： vip   coin
        String price = request.getParameter("price");
        price = "0.01";// 测试金额，1分钱
        String plat = request.getParameter("plat");// 根据平台的名称查找appid和appsecret
        WxConfig wxConfig = testService.getWxPayConfig(plat);
        String appId = wxConfig.getAppId();
        String secret = wxConfig.getAppSecret();
        String key = wxConfig.getApiSecret();
        String domain = wxConfig.getWxDomain();
        String openId = "";

        if( StringUtils.isEmpty(request.getParameter("code")) ){

            String url = request.getScheme() + "://" + request.getServerName() + request.getRequestURI() + "?" + request.getQueryString();
            String url2 = authorizeService.getAuthorizeBaseUrl(appId,url,"STATE#wechat_redirect");
            try {
                response.sendRedirect(url2);
                log.info("去获取code");
                return "redirect:"+url2;
            } catch (IOException e) {
                response.getWriter().print(e.toString());
                e.printStackTrace();
            }
        }else{
            // 有code
            String code = request.getParameter("code");
            String apiUrl = WeChatConfig.getUrl("useraccesstoken.get")
                    .replace(ConstantsPlaceholder.APPID, appId)
                    .replace(ConstantsPlaceholder.SECRET, secret)
                    .replace(ConstantsPlaceholder.CODE, code);
            String rep = HttpUtils.get(apiUrl);

            JSONObject myJsonObject = (JSONObject) JSONObject.parse( rep);

            openId = myJsonObject.getString("openid");
            String amount = String.format("%d", 100);
            String out_trade_no = "C"+Funutil.getOrdersn();



            // 创建订单
            PayOrder payOrder = new PayOrder();
            payOrder.setCreatetime( System.currentTimeMillis()/1000+"" );
            payOrder.setOrdersn( out_trade_no );
            payOrder.setPlat( plat );
            payOrder.setPrice( Double.valueOf( price ) );
            UsernameToken getUser = testService.getUser();
            payOrder.setUserid( getUser.getUserId() );
            payOrder.setWechat_id( openId );

            log.info( "时间" );
            log.info( payOrder.getCreatetime()+"" );

            testService.addPayOrder( payOrder );



            Map<String, String> data = new HashMap<>();
            data.put("body", "gok-充值");
            data.put("out_trade_no", out_trade_no );
            data.put("device_info", "");
            data.put("fee_type", "CNY");
            data.put("total_fee", (int)(payOrder.getPrice()*100) +"" );
            data.put("spbill_create_ip", "");
            data.put("notify_url", "http://gok.tc2stgs.com/wxpay/notify");
            data.put("trade_type", "JSAPI");
            data.put("openid", openId);
            data.put("attach", type);
            data.put("nonce_str", WXPayUtil.generateUUID());
            log.info("下单的数据"+new Gson().toJson( data ));
            Map<String, String> result = getWxPay().unifiedOrder(data);

            log.info("下单返回的数据"+new Gson().toJson( result ));

            Map<String, String> mapreq = new HashMap();
            if( result.size()  > 0 ){
                mapreq.put("appId", result.get("appid"));
                long t = System.currentTimeMillis()/1000;
                mapreq.put("timeStamp", t+"");
                String non = WXPayUtil.generateUUID();
                mapreq.put("nonceStr", non );
                mapreq.put("package", "prepay_id="+result.get("prepay_id") );
                mapreq.put("signType", "MD5" );
                // 签名
                String paySign = WXPayUtil.generateSignature(mapreq, key, SignType.HMACSHA256);

                mapreq.put("paySign", paySign);
            }
            request.setAttribute( "jsApiParameters", new Gson().toJson(mapreq) );
            return "wechatpay";
        }
        return "index";
    }

    @RequestMapping(value = "/notify", method = RequestMethod.POST)
    @ResponseBody
    public void payNotify( HttpServletRequest request, HttpServletResponse response ) throws Exception {

        StringBuilder wholeStr = new StringBuilder();
        try {
            BufferedReader br = request.getReader();
            String str;
            while((str = br.readLine()) != null){
                wholeStr.append(str);
            }
        } catch (IOException e) {
            log.error("getBodyString error", e);
        }

        Map<String, String> map = WXPayUtil.xmlToMap( wholeStr.toString() );
        String paySign = WXPayUtil.generateSignature(map, testService.getWxPaySecret(map.get("mch_id")), SignType.HMACSHA256);

        if( paySign.equals(  map.get("sign")  ) ){
            if( map.get("result_code").equals("SUCCESS") ){
                if( map.get("return_code").equals("SUCCESS") ){
                    double recmoney = Double.parseDouble(map.get("total_fee"))/100;

                    String type = map.get("attach");
                    if( "coin".equals(type) ){
                        if( testService.addMoney( recmoney, map.get("out_trade_no") ) ){
                            response.getWriter().print("success");
                        }else{
                            if( testService.addMoneyfail(map.get("out_trade_no")) ){
                                response.getWriter().print("success");
                            }
                        }
                    }else if( "vip".equals(type) ){
                        // vip充值
                        if( testService.addMoney( recmoney, map.get("out_trade_no") ) ){
                            response.getWriter().print("success");
                        }else{
                            if( testService.addMoneyfail(map.get("out_trade_no")) ){
                                response.getWriter().print("success");
                            }
                        }
                    }
                }
            }else{
                if( testService.addMoneyfail(map.get("out_trade_no")) ){
                    response.getWriter().print("success");
                }
            }

        }else{
            log.info(map.get("out_trade_no")+"验签失败");
        }
    }


    /**
     * 充值查询接口,3秒轮询一次
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/query", method = RequestMethod.GET)
    @ResponseBody
    public void querywxpub( HttpServletRequest request, HttpServletResponse response ) throws Exception {

        String plat = request.getParameter("plat");
        WxConfig wxConfig = testService.getWxPayConfig(plat);
        Gson gson = new Gson();
        List<PayOrder> payList = testService.getPayList( plat );// 查询所有status等于0的充值订单
        for( int i = 0;i<payList.size();i++ ){
            // 获得加密
            Map<String, String> params1 = new HashMap();
            params1.put("appid", wxConfig.getAppId() );
            params1.put("mch_id", wxConfig.getMchId() );
            params1.put("out_trade_no", payList.get(i).getOrdersn());
            params1.put("nonce_str", WXPayUtil.generateUUID());
            String signStr = WXPayUtil.generateSignature(params1, wxConfig.getApiSecret(), SignType.MD5);
            params1.put("sign", signStr);
            Map<String, String> result = getWxPay().orderQuery(params1);
//            log.info( gson.toJson( result ) );
            if( result == null ){
                continue;
            }
            if( result.get("return_code").equals("SUCCESS") ){
                if( result.get("return_msg").equals("OK") ){
                    if( result.get("result_code").equals("SUCCESS") ){
                        if( result.get("trade_state").equals("SUCCESS") ){
                            testService.addMoney(Double.parseDouble(result.get("total_fee"))/100, result.get("out_trade_no"));
                        }else{
                            testService.addMoneyfail( result.get("out_trade_no") );
                        }
                    }else{
                        testService.addMoneyfail( result.get("out_trade_no") );
                    }
                }else{
                    log.info("return_msg没通过");
                }
            }else{
                log.info("return_code没通过");
            }
        }
        return;
    }

}
